﻿using BZ.Logger;
using NDK.Module.BLL;
using NDK.Module.Model;
using NDK.Motion.BLL;
using NDK.Motion.MachineManager;
using NDK.Motion.Monitor;
using System;
using System.Collections.Concurrent;
using System.ComponentModel;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
//using Lmi3d.GoSdk.Messages;

namespace NDK.Module.StationLogic
{
    [Monitor(Description = "下料翻转工位")]
    public class UnloadFlip : StationLogic
    {
        #region 通用
        //记录当前步骤，用于步骤变化的比较
        private StationStep _curStep = StationStep.开始准备;
        //对外提供工位的步骤变化事件
        public override event PropertyChangedEventHandler PropertyChanged;
        //对外提供唯一实例
        public static UnloadFlip Instance = new UnloadFlip();
        //私有化的构造函数
        private UnloadFlip () : base()
        {
            this.Name = "下料翻转工位";
        }
        //步骤字段、属性
        private StationStep _step = StationStep.开始准备;
        [Monitor(Description = "当前步骤")]
        public StationStep Step
        {
            get
            {
                return _step;
            }
            set
            {
                if(_curStep != value)
                {
                    _step = value;
                    _curStep = value;

                    PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(value.ToString()));
                }
            }
        }
        #endregion

        #region 变量
        int PickCount;
        short result1 = 0;
        short result2 = 0;
        JUDGEMENT_RESULT ret_平台1结果;
        JUDGEMENT_RESULT ret_平台2结果;

        Task TaskAll, Task1, Task2;

        public ConcurrentQueue<JUDGEMENT_RESULT> ResultQueue1;
        public ConcurrentQueue<JUDGEMENT_RESULT> ResultQueue2;
        #endregion

        ManualResetEvent loadevent = new ManualResetEvent(false);

        /// <summary>
        /// 工站初始化
        /// </summary>
        public override void Init ()
        {
            base.Init();
            Step = StationStep.开始准备;
            logBaseInfo = "UnloadFlip";

            PickCount = 0;

            ResultQueue1 = new ConcurrentQueue<JUDGEMENT_RESULT>();
            ResultQueue2 = new ConcurrentQueue<JUDGEMENT_RESULT>();
        }

        private bool CylinderRotateHome ()
        {
            return CylinderMethod(false, (Machine.cy_下料翻转气缸, true));
        }

        private bool CylinderRotateWork ()
        {
            return CylinderMethod(true, (Machine.cy_下料翻转气缸, true));
        }

        private bool VacuumOn ()
        {
            return VacuumMethod(true, (Machine.do_下料翻转真空1吸, Machine.di_下料翻转真空1反馈, !Common.屏蔽治具1), (Machine.do_下料翻转真空2吸, Machine.di_下料翻转真空2反馈, !Common.屏蔽治具2));
        }

        /// <summary>
        /// 工站动作流程
        /// </summary>
        /// <param name="mode"></param>
        public override void ActionProcess ()
        {
            try
            {
                var s2 = Common.dic_plcComm_Bool["stPLC_PC.Spare_BOOL[0]"];//判断机械手是否处于安全位  true,危险位置 false,安全位置
                switch(Step)
                {
                    case StationStep.开始准备:
                        Step = StationStep.流程开始;
                        break;
                    case StationStep.流程开始:
                        if(Common.isWriteLog)
                        {
                            logCtStr = string.Empty;
                            swStepTime.Restart();
                            swStationCT.Restart();
                            logCtStr += $"{logBaseInfo},UnloadFlipStation 工站开始,{swStepTime.ElapsedMilliseconds},{Environment.NewLine}";
                            swStepTime.Restart();
                        }
                        Step = StationStep.工站复原;
                        break;

                    case StationStep.工站复原:
                        if(MotionControl.AxesMove(Machine.pos_Unloading_初始位) && CylinderRotateHome())
                        {
                            工位要料 = true;
                            Step = StationStep.等待上工位开完成;
                        }
                        break;

                    case StationStep.等待上工位开完成:
                        if(MeasureStation.Instance.工位完成)
                        {
                            Common.sw11.Restart();
                            Step = StationStep.轴接料位;
                        }
                        break;

                    case StationStep.轴接料位:
                        if(MotionControl.AxesMove(Machine.pos_Unloading_取料位))
                        {
                            MeasureStation.Instance.VacuumOff();
                            Step = StationStep.打开真空;
                        }
                        break;

                    case StationStep.打开真空:
                        if(VacuumOn())
                        {
                            Step = StationStep.轴初始位;
                        }
                        break;

                    case StationStep.轴初始位:
                        if(MotionControl.AxesMove(Machine.pos_Unloading_初始位) && VacuumOn())
                        {
                            工位要料 = false;
                            Step = StationStep.结果计算;
                        }
                        break;

                    case StationStep.结果计算:
                        if(!Common.屏蔽算法)
                        {
                            if(!Common.屏蔽治具1)
                            {
                                Task1 = Task.Run(async () =>
                                {
                                    while(ResultQueue1.Count < 1)
                                    {
                                        await Task.Delay(100);
                                    }
                                    ResultQueue1.TryDequeue(out ret_平台1结果);
                                    result1 = 1;
                                    if(ret_平台1结果 == JUDGEMENT_RESULT.NG)
                                    {
                                        result1 = 2;
                                    }
                                    else if(ret_平台1结果 == JUDGEMENT_RESULT.ORT)
                                    {
                                        result1 = 3;
                                    }
                                });
                            }
                            if(!Common.屏蔽治具2)
                            {
                                Task2 = Task.Run(async () =>
                                {
                                    while(ResultQueue2.Count < 1)
                                    {
                                        await Task.Delay(100);
                                    }
                                    ResultQueue2.TryDequeue(out ret_平台2结果);
                                    result2 = 1;
                                    if(ret_平台2结果 == JUDGEMENT_RESULT.NG)
                                    {
                                        result2 = 2;
                                    }
                                    else if(ret_平台2结果 == JUDGEMENT_RESULT.ORT)
                                    {
                                        result2 = 3;
                                    }
                                });
                            }
                        }
                        Step = StationStep.等待上工位关完成;
                        break;

                    case StationStep.等待上工位关完成:
                        if(!MeasureStation.Instance.工位完成)
                        {
                            Step = StationStep.气缸旋转;
                        }
                        break;

                    case StationStep.气缸旋转:
                        if(CylinderRotateWork() && VacuumOn())
                        {
                            Step = StationStep.轴放料位;
                        }
                        break;

                    case StationStep.轴放料位:
                        if(MotionControl.AxesMove(Machine.pos_Unloading_放料位))
                        {
                            Step = StationStep.联机判断;
                        }
                        break;

                    case StationStep.联机判断:
                        if(Common.是否联机上料PLC)
                        {
                            PickCount = Common.屏蔽治具1 ? 1 : 0;
                            Step = StationStep.允许取料;
                        }
                        else
                        {
                            Thread.Sleep(2000);
                            Machine.do_下料翻转真空1吸.OFF();
                            Machine.do_下料翻转真空2吸.OFF();
                            Machine.do_下料翻转真空1破.ON();
                            Machine.do_下料翻转真空2破.ON();
                            if(Common.手动启动)
                            {
                                if(AlarmPause("量测完成", "请取走物料", "点击确定,手动调整继续运行", "重新", "忽略报警，继续运行") == DialogResult.OK)
                                {
                                    break;
                                }
                            }
                            Step = StationStep.判断安全;
                        }
                        break;

                    case StationStep.允许取料:
                        if(PLCWriteMethod("下料工位", ($"stPC_PLC.bPick_Req[{PickCount}]", true, null)))
                        {
                            Common.AppendUiLog.Log($"下料工位发送允许{PickCount + 1}取料信号", LogType.Info);
                            Step = StationStep.等待到位;
                        }
                        break;

                    case StationStep.等待到位:
                        if(Common.dic_plcComm_Bool[$"stPLC_PC.bPick_InPos[{PickCount}]"])
                        {
                            Common.AppendUiLog.Log($"下料工位收到放料{PickCount + 1}到位信号", LogType.Info);
                            Step = StationStep.关闭真空;
                        }
                        break;

                    case StationStep.关闭真空:
                        if(PickCount == 0)
                        {
                            Machine.do_下料翻转真空1吸.OFF();
                            Machine.do_下料翻转真空1破.ON();
                        }
                        else
                        {
                            Machine.do_下料翻转真空2吸.OFF();
                            Machine.do_下料翻转真空2破.ON();
                        }
                        Step = StationStep.允许离开;
                        break;

                    case StationStep.允许离开:
                        if(PLCWriteMethod("下料工位", ($"stPC_PLC.bPick_LeaveAllow[{PickCount}]", true, null)))
                        {
                            Common.AppendUiLog.Log($"下料工位发送允许{PickCount + 1}离开信号", LogType.Info);
                            Step = StationStep.等待离开;
                        }
                        break;

                    case StationStep.等待离开:
                        if(Common.dic_plcComm_Bool[$"stPLC_PC.bPick_Comp[{PickCount}]"])
                        {
                            Machine.do_下料翻转真空1破.OFF();
                            Machine.do_下料翻转真空2破.OFF();
                            PLCWriteMethod("下料工位", ($"stPC_PLC.bPick_Req[{PickCount}]", false, null));
                            PLCWriteMethod("下料工位", ($"stPC_PLC.bPick_LeaveAllow[{PickCount}]", false, null));
                            Common.AppendUiLog.Log($"下料工位收到取料{PickCount + 1}离开信号", LogType.Info);
                            Step = StationStep.判断次数;
                        }
                        break;

                    case StationStep.判断次数:
                        if(PickCount == 0 && !Common.屏蔽治具2)
                        {
                            PickCount++;
                            Step = StationStep.允许取料;
                        }
                        else
                        {
                            PickCount = 0;
                            if(!Common.屏蔽治具1)
                            {
                                Task1.Wait();
                                PLCWriteMethod("下料工位", ("stPC_PLC.wCCDResult_1", null, result1));
                                Common.AppendUiLog.Log($"下料工位1发送结果：{result1}");
                            }
                            if(!Common.屏蔽治具2)
                            {
                                Task2.Wait();
                                PLCWriteMethod("下料工位", ("stPC_PLC.wCCDResult_2", null, result2));
                                Common.AppendUiLog.Log($"下料工位2发送结果：{result2}");
                            }
                            Step = StationStep.判断安全;
                        }
                        break;

                    case StationStep.判断安全:
                        if(s2)
                        {
                            Step = StationStep.流程结束;
                        }
                        break;

                    case StationStep.流程结束:
                        Common.sw11.Stop();
                        Common.GRREnd = false;

                        Common.GRR换穴 = 0;
                        Common.CurGRR循环次数 = 0;
                        if(Common.isWriteLog)
                        {
                            logCtStr += $"{logBaseInfo},Unload结束,{swStepTime.ElapsedMilliseconds},{Environment.NewLine}";
                            logCtStr += $"{logBaseInfo},Unload结束,{swStationCT.ElapsedMilliseconds},{Environment.NewLine}";
                            PublicMethod.WriteLogToTxt(logCtStr, $"000StepCT_{DateTime.Now:yyyyMMdd}", "7.Unload");
                        }
                        Step = StationStep.开始准备;
                        break;
                }
            }
            catch(Exception ex)
            {
                UILog_Error($"[UnloadFlip EmptyActionProcess Thread ERROR] {ex.Message}");
            }
        }

        public override void EmptyActionProcess ()
        {
            ActionProcess();
        }

        public override void GRRActionProcess ()
        {
            ActionProcess();
        }

        /// <summary>
        /// 工位步骤定义
        /// </summary>
        public enum StationStep
        {
            开始准备,
            流程开始,
            工站复原,
            等待上工位开完成,
            轴接料位,
            打开真空,
            轴初始位,
            结果计算,
            等待上工位关完成,
            气缸旋转,
            轴放料位,
            联机判断,

            允许取料,
            等待到位,
            关闭真空,
            允许离开,
            等待离开,

            判断次数,

            判断安全,
            流程结束,
        }
    }
}
